package com.qmx.qmxapp.utils;

import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;

import com.google.gson.Gson;
import com.koushikdutta.async.AsyncServer;
import com.koushikdutta.async.AsyncSocket;
import com.koushikdutta.async.ByteBufferList;
import com.koushikdutta.async.DataEmitter;
import com.koushikdutta.async.Util;
import com.koushikdutta.async.callback.CompletedCallback;
import com.koushikdutta.async.callback.ConnectCallback;
import com.koushikdutta.async.callback.DataCallback;
import com.koushikdutta.async.callback.WritableCallback;
import com.qmx.qmxapp.base.BaseApplication;
import com.qmx.qmxapp.constant.AppConstant;
import com.tencent.av.logger.Logger;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.HashMap;
import java.util.LinkedHashMap;

/**
 * @author chengxiangtong
 * @date 2018/11/22
 * version : 1.0
 * class describe：长连接
 */
public class SocketUtil implements ConnectCallback {

    //    1.包体：
    //    content = [
    //            'func' => 'auth@logins',  //请求函数
    //            'params' => ['token' => "4f106078-aaba-4f54-bb81-e25662043bc9"] //请求参数
    //            ]
    //            2.转json包体
    //    {"func":"auth@logins","params":{"token":"4f106078-aaba-4f54-bb81-e25662043bc9"}}
    //3.转16进制
    //7b2266756e63223a2261757468406c6f67696e73222c22706172616d73223a7b22746f6b656e223a2234663130363037382d616162612d346635342d626238312d653235363632303433626339227d7d
    //4.获取10进制包体字符长度
    //160
    //        5.获得10进制包长转16进制（小写字母）sprintf("%04x",160)
    //0xa0
    //        6.消息包 = 包长 + 包体
    //0xa07b2266756e63223a2261757468406c6f67696e73222c22706172616d73223a7b22746f6b656e223a2234663130363037382d616162612d346635342d626238312d653235363632303433626339227d7d


    private AsyncSocket socket;
    private static SocketUtil sendSocketData;
    private SocketDataCallback socketDataCallback;
    private SharedPreferences sharedPreferences = BaseApplication.getInstance().getSharedPreferences(BaseApplication.getInstance().getPackageName(), Context.MODE_PRIVATE);
    SharedPreferences.Editor editor = sharedPreferences.edit();

    private SocketUtil() {
        AsyncServer.getDefault().connectSocket(AppConstant.HOSTNAME, AppConstant.PORT, this);
    }

    public SocketDataCallback getSocketDataCallback() {
        return socketDataCallback;
    }

    public void setSocketDataCallback(SocketDataCallback socketDataCallback) {
        this.socketDataCallback = socketDataCallback;
    }

    public interface SocketDataCallback {
        void socketDataCallback(int code, JSONObject str);
    }

    public static SocketUtil getInstance() {
        return SingletonHolder.instance();
    }

    @Override
    public void onConnectCompleted(Exception ex, AsyncSocket socket) {
        if (ex != null) {
            Log.d("Socket", "连接出错");
            return;
        }
        socket.setDataCallback(new DataCallback() {
            @Override
            public void onDataAvailable(DataEmitter emitter, ByteBufferList bb) {
                JSONObject jsonObject = getDataHexString(bb);
                Log.d("onConnectCompleted", "接收到：" + jsonObject);
                int code = 0;
                try {
                    code = jsonObject.getInt("code");
                    if (code != 911) {//登录
                        if (code == AppConstant.MESSAGE_EVENT_ID_USER_SIGN_SUCCESS) {
                            socketDataCallback.socketDataCallback(code, jsonObject);
                        } else {//会议中的动作
                            socketDataCallback.socketDataCallback(code, jsonObject);
                        }
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        });
        socket.setClosedCallback(new CompletedCallback() {
            @Override
            public void onCompleted(Exception ex) {
                if (ex != null) {
                    Log.d("setClosedCallback", "setClosedCallback出错");
                    return;
                }
                Log.d("setClosedCallback", "setClosedCallback");
            }
        });
        socket.setEndCallback(new CompletedCallback() {
            @Override
            public void onCompleted(Exception ex) {
                if (ex != null) {
                    Log.d("setEndCallback", "setEndCallback出错");
                    return;
                }
                Log.d("setEndCallback", "setEndCallback");
            }
        });
        socket.setWriteableCallback(new WritableCallback() {
            @Override
            public void onWriteable() {
                Log.d("Socket", "onWriteable");
            }
        });
        this.socket = socket;
        Log.i("", "socket链接成功");
    }

    static LinkedHashMap<Object, Object> funcHashMap = null;
    static Gson g = new Gson();

    /**
     * 封装发送socket请求
     *
     * @param func
     * @param params
     * @return
     */
    public String socketData(String func, LinkedHashMap params) {
        if (funcHashMap == null) {
            funcHashMap = new LinkedHashMap<>();
        }
        funcHashMap.put("func", func);
        if (params != null) {
            funcHashMap.put("params", params);
        } else {
            return "00A67b22706172616d73223a7b22726f6f6d5f6964223a22393030303030303035222c22756964223a223130303035222c2274797065223a2230227d2c2266756e63223a226d656574696e674063616d657261227d";
        }
        String jsonString = g.toJson(funcHashMap);
        String str2Hex = StringUtils.str2HexStr(jsonString);
        int strLeng = str2Hex.length();
        String body = StringUtils.HexAddZero(strLeng) + str2Hex;

        funcHashMap.clear();

        Log.i("jsonString", jsonString);
        Log.i("DefaultSendBean", body);
        //        Log.d("PushService", "onWriteable");

        return body;
    }

    /**
     * 解析socket返回的数据
     *
     * @param bb
     */
    public JSONObject getDataHexString(final ByteBufferList bb) {
        JSONObject jsonObject = null;
        try {
            String result = new String(bb.getAllByteArray(), "utf-8");
            String str2Hex = StringUtils.convertUTF8ToString(result.substring(4, result.length()));
            jsonObject = new JSONObject(str2Hex);
            Log.i("getDataHexString", jsonObject.toString());

            result = null;
            str2Hex = null;
            //            Log.d("str2Hex", new JSONObject(jsonObject.opt("data").toString()).opt("client_id").toString());
            //            Log.d("str2Hex", (String) new JSONObject((String) jsonObject.opt("data")).opt("client_id"));

        } catch (Exception e) {
            e.printStackTrace();
        }
        return jsonObject;
    }

    public void sendSocketData(String funData, LinkedHashMap hashMap) {
        if (socket == null) {
            Log.i("sendSocketData", "socket==null");
            return;
        }
        Util.writeAll(socket, socketData(funData, hashMap).getBytes(), new CompletedCallback() {
            @Override
            public void onCompleted(Exception ex) {
                if (ex != null) {
                    Log.d("PushService", "writeAll出错");
                    return;
                }
                if (hashMap != null) {
                    Log.d("SendSocket", "发送了：" + hashMap.toString());
                    hashMap.clear();
                }
            }
        });
    }

    /**
     * 发送Socket退出登录命令
     */
    //    public void SendLogoutOrder() {
    //        if (socket == null) {
    //            Logger.e("socket==null");
    //            return;
    //        }
    //        String Data = "{\"header\":{\"cmd\":\"1001\"},\"body\":{\"data\":\"\"}}";
    //        Util.writeAll(socket, Data.getBytes(), new CompletedCallback() {
    //            @Override
    //            public void onCompleted(Exception ex) {
    //                if (ex != null) {
    //                    Log.d("SendSocket", "writeAll出错");
    //                    return;
    //                }
    //                Log.d("SendSocket", "发送了：" + Data);
    //            }
    //        });
    //    }

    /**
     * 发送Socket心跳命令
     */
    public void sendHeartbeat() {
        if (socket == null) {
            Log.i("sendHeartbeat==", "socket==null");
            return;
        }
        Util.writeAll(socket, socketData("ping@pong", null).getBytes(), new CompletedCallback() {
            @Override
            public void onCompleted(Exception ex) {
                if (ex != null) {
                    Log.d("sendHeartbeat", "writeAll出错");
                    return;
                }
                Log.d("sendHeartbeat", "发送了：心跳包");
            }
        });
    }

    public void clearSendSocketData() {
        sendSocketData = null;
    }

    private static class SingletonHolder {
        public static SocketUtil instance() {
            if (sendSocketData == null) {
                sendSocketData = new SocketUtil();
            }
            return sendSocketData;
        }
    }

}
